home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / bm_cpio.gz / unixbm.cpio / send.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  12KB  |  531 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <time.h>
  4. #include <ctype.h>
  5. #if    (defined(UNIX) || defined(MICROSOFT))
  6. #include <sys/types.h>
  7. #endif
  8. #include "bm.h"
  9.  
  10. struct addr *addrecip();
  11. char *ptime();
  12.  
  13. /* send a message */
  14. dosmtpsend(mfp,toargs,nargs,subject)
  15. FILE *mfp;
  16. char *toargs[];
  17. int nargs;
  18. char *subject;
  19. {
  20.     char    smtp_subject[LINELEN], 
  21.         tstring[LINELEN];
  22.     char    *tmpnam();
  23.     FILE     *fpin;
  24.     char    *p;
  25.     char     *tf = "bmXXXXXX";        /* temp file name */
  26.     int    c;
  27.     int    n;
  28.     long    sequence;
  29.     struct    addr *tolist,*tp;
  30.     register FILE    *tfile;
  31.     time_t    t;
  32.  
  33.  
  34.     if (nargs == 0) {
  35.         printf("No recpients\n");
  36.         return 0;
  37.     }
  38.     fpin = mfp;
  39.     if ((tolist = make_tolist(nargs,toargs)) == NULLADDR) {
  40.         printf("Send aborted\n");
  41.         return 0;
  42.     }
  43.  
  44.     sequence = get_msgid();
  45.  
  46.     time(&t);
  47.     mktemp(tf);
  48.         /* open textfile for write */
  49.     if ((tfile = fopen(tf,"w+")) == NULLFILE) {
  50.         perror(tf);
  51.         del_addrlist(tolist);
  52.         return 1;
  53.     }
  54.  
  55.     if (!qflag) {
  56.         /* write RFC822-compatible headers using above information */
  57.         fprintf(tfile,"Date: %s",ptime(&t));
  58.         fprintf(tfile,"Message-Id: <%ld@%s>\n",sequence,hostname);
  59.         fprintf(tfile,"From: %s@%s",username,hostname);
  60.         if (fullname != NULLCHAR && *fullname != '\0')
  61.             fprintf(tfile," (%s)",fullname);
  62.         fprintf(tfile,"\n");
  63.         if (replyto != NULLCHAR && *replyto != '\0')
  64.             fprintf(tfile,"Reply-To: %s\n",replyto);
  65.         strcpy(tstring,"To: ");
  66.         for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  67.             strcat(tstring,tp->user);
  68.             if (tp->host != NULLCHAR || *tp->host != '\0') {
  69.                 strcat(tstring,"@");
  70.                 strcat(tstring,tp->host);
  71.             }
  72.             n = strlen(tstring);
  73.             if (tp->next) {
  74.                 if (n > 50) {
  75.                     fprintf(tfile,"%s,\n\t",tstring);
  76.                     if (tty) printf("%s,\n ",tstring);
  77.                     *tstring = '\0';
  78.                 } else
  79.                     strcat(tstring,", ");
  80.             }
  81.         }
  82.         fprintf(tfile,"%s\n",tstring);
  83.         if (tty) printf("%s\n",tstring); 
  84.  
  85.         *smtp_subject = '\0';
  86.         if (subject == NULL && tty) {
  87.             /* prompt and get Subject: */
  88.             printf("Subject: ");
  89.             gets(smtp_subject);
  90.         } else {
  91.             strcpy(smtp_subject,subject);
  92.             if(tty) printf("Subject: %s\n",smtp_subject);
  93.         }
  94.         fprintf(tfile,"Subject: %s\n",smtp_subject);
  95.         fprintf(tfile,"\n");       /* add empty line as separator */
  96.     }
  97.  
  98.     if (!tty && fpin == NULLFILE)
  99.         fpin = stdin;
  100.  
  101.     if (fpin != NULLFILE ) {
  102.         while((c = getc(fpin)) != EOF)
  103.             if(putc(c,tfile) == EOF)
  104.                 break;
  105.         if (ferror(tfile)) {
  106.             perror("tmp file");
  107.             (void) fclose(tfile);
  108.             (void) unlink(tf);
  109.             return 1;
  110.         }
  111.     } else {
  112.         /* sending a message not from a file */
  113.         /* copy text from console to the file */
  114.         printf("\nType message text.  Enter a '.' or ctrl/D in column one to end.");
  115.         printf("\nCommands: ~p - redisplay msg, ~e - invoke editor, ~? - help\n\n");
  116.         for(;;) {
  117.             /* read line from console  ie stdin */
  118.             if (gets(tstring) == NULLCHAR)
  119.                 break;
  120.             rip(tstring);
  121.             if(strcmp(tstring,".") == 0 || tstring[0] == '\004')
  122.                 break;
  123.             if (*tstring == '~' ) {
  124.                 switch(tstring[1]) {
  125.                 case 'p':
  126.                     /* Print the message so far */
  127.                     fseek(tfile,0L,0);
  128.                     while (fgets(tstring,sizeof(tstring),tfile) != NULLCHAR)
  129.                         fputs(tstring,stdout);
  130.                     break;
  131.                 case 'e':
  132.                     /* Drop into editor */
  133.                     (void) fclose(tfile);
  134.                     if (editor == NULLCHAR) {
  135.                         printf("No editor defined\n");
  136.                         break;
  137.                     }
  138.                     sprintf(tstring,"%s %s",editor,tf);
  139.                     /* call editor to enter message text */
  140.                     if (system(tstring))
  141.                         printf("unable to invoke editor\n");
  142.                     tfile = fopen(tf,"a+");
  143.                     break;
  144.                 case 'q':
  145.                     (void) fclose(tfile);
  146.                     (void) unlink(tf);
  147.                     printf("Abort\n");
  148.                     return 0;
  149.                 case 'r': 
  150.                     {
  151.                         FILE  *infl;
  152.                         p = &tstring[2];
  153.                         while(*p == ' ' || *p == '\t')
  154.                             p++;
  155.                         if (*p == '\0')
  156.                             printf("No file name specified\n");
  157.                         else
  158.                             if((infl = fopen(p,"r")) == NULLFILE)
  159.                                 printf("No such file\n");
  160.                             else {
  161.                                 printf("Reading file %s\n",p);
  162.                                 while((c = getc(infl)) != EOF)
  163.                                     if(putc(c,tfile) == EOF)
  164.                                         break;
  165.                                 if (ferror(tfile)) {
  166.                                     perror("tmp file");
  167.                                     (void) fclose(tfile);
  168.                                     (void) unlink(tf);
  169.                                     return 1;
  170.                                 }
  171.                                 (void) fclose(infl);
  172.                             }
  173.  
  174.                         break;
  175.                     }
  176.                 case 'm': 
  177.                     {
  178.                         int    msg;
  179.                         p = &tstring[2];
  180.                         while(*p == ' ' || *p == '\t')
  181.                             p++;
  182.                         if (*p == '\0')
  183.                             msg = current;
  184.                         else
  185.                             msg = atoi(p);
  186.                         if (mfile == NULLFILE || msg < 1 || msg > nmsgs)
  187.                             printf("no such message\n");
  188.                         else {
  189.                             printf("Inserting message %d\n",msg);
  190.                             msgtofile(msg,tfile,0);
  191.                         }
  192.                         break;
  193.                     }
  194.                 case '~':
  195.                     fprintf(tfile,"%s\n",&tstring[1]);
  196.                     break;
  197.                 case '?':
  198.                     printf("~e - Invoke Editor\n");
  199.                     printf("~p - Display message buffer\n");
  200.                     printf("~q - Abort this message\n");
  201.                     printf("~r file - Read file into buffer\n");
  202.                     printf("~m msg - message into buffer\n");
  203.                     printf("~~ - Enter a ~ into message\n");
  204.                     break;
  205.                 default:
  206.                     printf("Unknown ~ escape. ~? for help\n");
  207.                 }
  208.                 printf("(continue)\n");
  209.             } else
  210.                 fprintf(tfile,"%s\n",tstring);
  211.         }
  212.         printf("EOF\n");
  213.  
  214.     }
  215.     queuejob(tfile,tolist);
  216.     recordmsg(tfile,tolist->user);     /* save copy for sender */
  217.     (void) fclose(tfile);
  218.     del_addrlist(tolist);
  219.     (void) unlink(tf);
  220.     return 0;
  221. }
  222.  
  223. /* forward a message in its orginal form */
  224. bouncemsg(mfp,toargs,nargs)
  225. FILE *mfp;
  226. char *toargs[];
  227. int nargs;
  228. {
  229.     struct    addr *list;
  230.     if (nargs == 0) {
  231.         printf("No recpients\n");
  232.     } else if ((list = make_tolist(nargs,toargs)) == NULLADDR) {
  233.         printf("Bad to list\n");
  234.     } else {
  235.         queuejob(mfp,list);
  236.         del_addrlist(list);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. /* Return Date/Time in Arpanet format in passed string */
  242. /* Print out the time and date field as
  243.  *        "DAY day MONTH year hh:mm:ss ZONE"
  244.  */
  245. char *
  246. ptime(t)
  247. long *t;
  248. {
  249.     register struct tm *ltm;
  250.     struct tm *localtime();
  251.     static char tz[4];
  252.     static char str[40];
  253.     extern char *getenv();
  254.     char *p;
  255.     static char *days[7] = {
  256.     "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  257.  
  258.     static char *months[12] = {
  259.         "Jan","Feb","Mar","Apr","May","Jun",
  260.         "Jul","Aug","Sep","Oct","Nov","Dec" };
  261.  
  262.     /* Read the system time */
  263.     ltm = localtime(t);
  264.  
  265.     if (*tz == '\0')
  266.         if ((p = getenv("TZ")) == NULL)
  267.             strcpy(tz,"GMT");
  268.         else
  269.             strncpy(tz,p,3);
  270.  
  271.     /* rfc 822 format */
  272.     sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
  273.         days[ltm->tm_wday],
  274.         ltm->tm_mday,
  275.         months[ltm->tm_mon],
  276.         ltm->tm_year,
  277.         ltm->tm_hour,
  278.         ltm->tm_min,
  279.         ltm->tm_sec,
  280.         tz);
  281.     return(str);
  282. }
  283.  
  284. /* save copy in the record file */
  285. recordmsg(dfile,to) 
  286. FILE *dfile;
  287. char *to;
  288. {
  289.     register int c;
  290.     FILE     *fp;
  291.     time_t    t;
  292.  
  293.     if (record == NULLCHAR)
  294.         return 1;
  295.     fseek(dfile,0L,0);
  296.     if ((fp = fopen(record,"a")) == NULLFILE) {
  297.         printf("Unable to append to %s\n",record);
  298.     } else {
  299.         (void) time(&t);
  300.         fprintf(fp,"From %s %s",to,ctime(&t));
  301.         while((c = getc(dfile)) != EOF)
  302.             if(putc(c,fp) == EOF)
  303.                 break;
  304.         if (ferror(fp)) {
  305.             (void) fclose(fp);
  306.             return 1;
  307.         }
  308.         (void) fclose(fp);
  309.     }
  310.     return 0;
  311. }
  312.  
  313. /* place a mail job in the outbound queue */
  314. int
  315. queuejob(dfile,tolist)
  316. FILE *dfile;
  317. struct addr *tolist;
  318. {
  319.     FILE *fp;
  320.     char tmpstring[50];
  321.     register struct addr *tp,*sp;
  322.     char prefix[9];
  323.     int c;
  324.     long id;
  325.  
  326.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  327.         if (tp->sent)
  328.             continue;
  329.         fseek(dfile,0L,0);
  330.         id = get_msgid();
  331.         sprintf(prefix,"%ld",id);
  332.         (void) mlock(mqueue,prefix);
  333.         sprintf(tmpstring,"%s/%s.txt",mqueue,prefix);
  334.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  335.             printf("unable to open %s\n",tmpstring);
  336.             (void) rmlock(mqueue,prefix);
  337.             return 1;
  338.         }
  339.         while((c = getc(dfile)) != EOF)
  340.             if(putc(c,fp) == EOF)
  341.                 break;
  342.         if (ferror(fp)) {
  343.             (void) fclose(fp);
  344.             (void) rmlock(mqueue,prefix);
  345.             return 1;
  346.         }
  347.         (void) fclose(fp);
  348.         sprintf(tmpstring,"%s/%s.wrk",mqueue,prefix);
  349.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  350.             (void) rmlock(mqueue,prefix);
  351.             return 1;
  352.         }
  353.         fprintf(fp,"%s\n%s@%s\n",tp->host,username,hostname);
  354.         fprintf(fp,"%s@%s\n",tp->user,tp->host);
  355.         tp->sent++;
  356.         /* find and other addresses to the same host */
  357.         for (sp = tp->next; sp != NULLADDR; sp = sp->next) {
  358.             if (sp->sent)
  359.                 continue;
  360.             if (strcmp(tp->host,sp->host) == 0) {
  361.                 fprintf(fp,"%s@%s\n",sp->user,sp->host);
  362.                 sp->sent++;
  363.             }
  364.         }
  365.         (void) fclose(fp);
  366.         (void) rmlock(mqueue,prefix);
  367.     }
  368.     return 0;
  369. }
  370.  
  371. #define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
  372. #define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
  373.  
  374. /* check for and alias and expand alais into a address list */
  375. struct addr *
  376. expandalias(head, user)
  377. struct addr **head;
  378. char *user;
  379. {
  380.     FILE *fp;
  381.     register char *s,*p,*h;
  382.     int inalias;
  383.     struct addr *tp;
  384.     char buf[LINELEN];
  385.     
  386.     fp = fopen(alias, "r");
  387.     
  388.         /* no alias file found */
  389.     if (fp == NULLFILE)
  390.         return addrecip(head, user, hostname);
  391.  
  392.     inalias = 0;
  393.     while (fgets(buf,LINELEN,fp) != NULLCHAR) {
  394.         p = buf;
  395.         if ( *p == '#' || *p == '\0')
  396.             continue;
  397.         rip(p);
  398.  
  399.         /* if not in an matching entry skip continuation lines */
  400.         if (!inalias && isspace(*p))
  401.             continue;
  402.  
  403.         /* when processing an active alias check for a continuation */
  404.         if (inalias) {
  405.             if (!isspace(*p)) 
  406.                 break;    /* done */
  407.         } else {
  408.             s = p;
  409.             SKIPWORD(p);
  410.             *p++ = '\0';    /* end the alias name */
  411.             if (strcmp(s,user) != 0)
  412.                 continue;    /* no match go on */
  413.             inalias = 1;
  414.         }
  415.  
  416.         /* process the recipients on the alias line */
  417.         SKIPSPACE(p);
  418.         while(*p != '\0' && *p != '#') {
  419.             s = p;
  420.             SKIPWORD(p);
  421.             if (*p != '\0')
  422.                 *p++ = '\0';
  423.             /* find hostname */
  424.             if ((h = strchr(s,'@')) != NULLCHAR)
  425.                 *h++ = '\0';
  426.             else
  427.                 h = hostname;
  428.             tp = addrecip(head,s,h);
  429.             SKIPSPACE(p);
  430.         }
  431.     }
  432.     (void) fclose(fp);
  433.  
  434.     if (inalias)    /* found and processed and alias. */
  435.         return tp;
  436.  
  437.     /* no alias found treat as a local address */
  438.     return addrecip(head, user, hostname);
  439. }
  440.  
  441. /* convert a arg list to an list of address structures */
  442. struct addr *
  443. make_tolist(argc,argv)
  444. int argc;
  445. char *argv[];
  446. {
  447.     struct addr *tolist, *tp;
  448.     char *user, *host;
  449.     int i;
  450.     tolist = NULLADDR;
  451.     for (i = 0; i < argc; i++) {
  452.         user = argv[i];
  453.         if ((host = strchr(user ,'@')) != NULLCHAR) {
  454.             *host++ = '\0';
  455.             /* if it matches our host name */
  456.             if (stricmp(host,hostname) == 0)
  457.                 host = NULLCHAR;
  458.         }
  459.  
  460.         if (host == NULLCHAR)    /* a local address */
  461.             tp = expandalias(&tolist,user);
  462.         else        /* a remote address */
  463.             tp = addrecip(&tolist, user, host);
  464.  
  465.         if (tp == NULLADDR) {
  466.             printf("Out of memory\n");
  467.             del_addrlist(tolist);
  468.             return NULLADDR;
  469.         }
  470.     }
  471.     return tolist;
  472. }
  473.  
  474. /* delete a list of mail addresses */
  475. del_addrlist(list)
  476. struct addr *list;
  477. {
  478.     struct addr *tp, *tp1;;
  479.     for (tp = list; tp != NULLADDR; tp = tp1) {
  480.         tp1 = tp->next;
  481.         if (tp->user != NULLCHAR);
  482.             free(tp->user);
  483.         if (tp->host != NULLCHAR);
  484.             free(tp->host);
  485.         (void) free((char *)tp);
  486.     }
  487. }
  488.  
  489. /* add an address to the from of the list pointed to by head 
  490. ** return NULLADDR if out of memory.
  491. */
  492. struct addr *
  493. addrecip(head,user,host)
  494. struct addr **head;
  495. char *user, *host;
  496. {
  497.     register struct addr *tp;
  498.  
  499.     tp = (struct addr *)calloc(1,sizeof(struct addr));
  500.     if (tp == NULLADDR)
  501.         return NULLADDR;
  502.  
  503.     tp->next = NULLADDR;
  504.  
  505.     /* allocate storage for the user's login */
  506.     if ((tp->user = malloc((unsigned)strlen(user)+1)) == NULLCHAR) {
  507.         (void) free((char *)tp);
  508.         return NULLADDR;
  509.     }
  510.     strcpy(tp->user,user);
  511.  
  512.     /* allocate storage for the host name */
  513.     if (host != NULLCHAR)
  514.         if ((tp->host = malloc((unsigned)strlen(host)+1)) == NULLCHAR) {
  515.             (void) free(tp->user);
  516.             (void) free((char *)tp);
  517.             return NULLADDR;
  518.         }
  519.     strcpy(tp->host,host);
  520.  
  521.     /* add entry to front of existing list */
  522.     if (*head == NULLADDR)
  523.         *head = tp;
  524.     else {
  525.         tp->next = *head;
  526.         *head = tp;
  527.     }
  528.     return tp;
  529.  
  530. }
  531.